/**
 * Copyright (C) 2010 David Simonek <dafesimonek@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.dafe.partyband.gui.exports;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.dafe.partyband.db.api.ISong;
import org.dafe.partyband.db.api.ISongResource;
import org.dafe.partyband.dochandler.OOActions;
import org.dafe.partyband.gui.Utilities;
import org.dafe.partyband.importer.api.IImporterServices;
import org.dafe.partyband.importer.api.IMimeTypeDetector;
import org.dafe.partyband.importer.api.IMimeTypeDetector.ContentType;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;

public final class ExportVisualPanel1 extends JPanel {

    private final IMimeTypeDetector mimeDetector = Lookup.getDefault().lookup(IImporterServices.class).getMimeDetector();

    private Result result;
    final Lookup.Result<ISongResource> resourcesLkpResult;
        // TBD - change to localized display strings
    final OOActions.DocumentType[] docTypes = new OOActions.DocumentType[] {
            null,
            OOActions.DocumentType.WORD,
            OOActions.DocumentType.PDF };
    private final ExportListModel exportListModel;
    private final Type2ExportModel type2ExportModel;

    /** Creates new form ExportVisualPanel1 */
    public ExportVisualPanel1(final ExportWizardPanel1 wizardPanel, final Lookup.Result<ISongResource> resourcesLkpResult) {
        this.resourcesLkpResult = resourcesLkpResult;
        initComponents();

        result = new Result();

        exportListModel = new ExportListModel();
        resList.setModel(exportListModel);
        resourcesLkpResult.addLookupListener(exportListModel);

        String[] docDisplayNames = new String[docTypes.length];
        for (int i = 0; i < docTypes.length; i++) {
            if (docTypes[i] == null) {
                docDisplayNames[i] = "No conversion";
            } else {
                docDisplayNames[i] = docTypes[i].getConversionFilter();
            }
        }
        DefaultComboBoxModel conversionM = new DefaultComboBoxModel(docTypes);
        conversionCombo.setModel(conversionM);
        
        type2ExportModel = new Type2ExportModel();
        type2ExportCombo.setModel(type2ExportModel);
        type2ExportCombo.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                exportListModel.resultChanged(null);
            }
        });
        type2ExportCombo.setSelectedItem(IMimeTypeDetector.ContentType.TEXT_WITH_CHORDS);
        
        dirTextField.getDocument().addDocumentListener(new DocumentListener() {

            public void insertUpdate(DocumentEvent e) {
                wizardPanel.fireChangeEvent();
            }

            public void removeUpdate(DocumentEvent e) {
                wizardPanel.fireChangeEvent();
            }

            public void changedUpdate(DocumentEvent e) {
                wizardPanel.fireChangeEvent();
            }


        });

    }
    
    private class Type2ExportModel extends AbstractListModel implements ComboBoxModel {

        final IMimeTypeDetector.ContentType[] contentTypes = IMimeTypeDetector.ContentType.values();
        private Object selItem;
        
        public int getSize() {
            return contentTypes.length + 1;
        }

        public Object getElementAt(int index) {
            if (index == 0) {
                return NbBundle.getMessage(ExportVisualPanel1.class, "LBL_AllContentTypes");
            }
            return contentTypes[index - 1];
        }

        public void setSelectedItem(Object anItem) {
            selItem = anItem;
        }

        public Object getSelectedItem() {
            return selItem;
        }
        
    } 

    private class ExportListModel extends AbstractListModel implements LookupListener {
        
        private List<ISongResource> list2Export;

        public ExportListModel() {
            fillList2Export();
        }
        
        public int getSize() {
            return list2Export.size();
        }

        public Object getElementAt(int index) {
            ISongResource res = list2Export.get(index);
            if (res != null) {
                if (numberingCheckBox.isSelected()) {
                    int sizeCharCount = String.valueOf(getSize()).length();
                    StringBuilder sb = new StringBuilder(Utilities.getStringNumber(index + 1, sizeCharCount));
                    sb.append("_");
                    sb.append(res.getFileName());
                    return sb.toString();
                } else {
                    return res.getFileName();
                }
            }
            return null;
        }

        public void resultChanged(LookupEvent ev) {
            fillList2Export();
            
            fireContentsChanged(this, 0, getSize() - 1);
        }
        
        public List<ISongResource> getList2Export() {
            return list2Export;
        }
        
        private void fillList2Export() {
            List<ISongResource> resList = (List<ISongResource>) resourcesLkpResult.allInstances();
            boolean preferredOnly = preferredOnlyCheckBox.isSelected();
            Object selItem = type2ExportCombo.getSelectedItem();
            IMimeTypeDetector.ContentType selType = selItem instanceof IMimeTypeDetector.ContentType
                    ? (IMimeTypeDetector.ContentType)selItem : null;
            if (!preferredOnly && selType == null) {
                list2Export = resList;
            } else {
                list2Export = new ArrayList<ISongResource>();
                for (ISongResource curRes : resList) {
                    // exclude not selected content types
                    if (selType != null && !Utilities.isResourceOfType(curRes, selType)) {
                        continue;
                    }
                    // exclude not preferred resources
                    if (preferredOnly) {
                        ISong parentSong = curRes.getParent();
                        if (parentSong != null) {
                            ContentType resType = mimeDetector.getContentType(curRes.getMimeType());
                            if (!curRes.equals(Utilities.getPreferredResourceOfType(parentSong, resType))) {
                                continue;
                            }
                        } else {
                            if (!curRes.isPreferred()) {
                                continue;
                            }
                        }
                    }
                    list2Export.add(curRes);
                }
            }
        }
        
    }

    @Override
    public String getName() {
        return NbBundle.getMessage(ExportVisualPanel1.class, "LBL_ChooseDirectory");
    }

    public Result getResult () {
        result.resources = exportListModel.getList2Export();
        int selIndex = conversionCombo.getSelectedIndex();
        result.convertTo = selIndex <= 0 ? null : docTypes[selIndex];
        int resCount = result.resources.size();
        result.fileNames = new ArrayList<String>(resCount);
        for (int i = 0; i < resCount; i++) {
            result.fileNames.add((String)exportListModel.getElementAt(i));
        }
        return result;
    }

    public static class Result {
        public List<ISongResource> resources;
        public File exportDir;
        public OOActions.DocumentType convertTo;
        public List<String> fileNames;
    }

    public File getChosenDir () {
        return new File(dirTextField.getText());
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        resList = new javax.swing.JList();
        jLabel2 = new javax.swing.JLabel();
        dirTextField = new javax.swing.JTextField();
        dirButton = new javax.swing.JButton();
        conversionCombo = new javax.swing.JComboBox();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        type2ExportCombo = new javax.swing.JComboBox();
        preferredOnlyCheckBox = new javax.swing.JCheckBox();
        numberingCheckBox = new javax.swing.JCheckBox();

        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ExportVisualPanel1.class, "ExportVisualPanel1.jLabel1.text")); // NOI18N

        jScrollPane1.setViewportView(resList);

        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(ExportVisualPanel1.class, "ExportVisualPanel1.jLabel2.text")); // NOI18N

        dirTextField.setText(org.openide.util.NbBundle.getMessage(ExportVisualPanel1.class, "ExportVisualPanel1.dirTextField.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(dirButton, org.openide.util.NbBundle.getMessage(ExportVisualPanel1.class, "ExportVisualPanel1.dirButton.text")); // NOI18N
        dirButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                dirButtonActionPerformed(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(ExportVisualPanel1.class, "ExportVisualPanel1.jLabel3.text",new Object[] {})); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(ExportVisualPanel1.class, "ExportVisualPanel1.jLabel4.text")); // NOI18N

        preferredOnlyCheckBox.setSelected(true);
        org.openide.awt.Mnemonics.setLocalizedText(preferredOnlyCheckBox, org.openide.util.NbBundle.getMessage(ExportVisualPanel1.class, "ExportVisualPanel1.preferredOnlyCheckBox.text")); // NOI18N
        preferredOnlyCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                preferredOnlyCheckBoxActionPerformed(evt);
            }
        });

        numberingCheckBox.setSelected(true);
        org.openide.awt.Mnemonics.setLocalizedText(numberingCheckBox, org.openide.util.NbBundle.getMessage(ExportVisualPanel1.class, "ExportVisualPanel1.numberingCheckBox.text")); // NOI18N
        numberingCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                numberingCheckBoxActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 418, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel2)
                                    .addComponent(jLabel3))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(conversionCombo, 0, 209, Short.MAX_VALUE)
                                    .addComponent(dirTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 209, Short.MAX_VALUE)))
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                                .addComponent(jLabel4)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(layout.createSequentialGroup()
                                        .addComponent(preferredOnlyCheckBox)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(numberingCheckBox)
                                        .addGap(0, 0, Short.MAX_VALUE))
                                    .addComponent(type2ExportCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(dirButton))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 167, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(dirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(dirButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(conversionCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(type2ExportCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(preferredOnlyCheckBox)
                    .addComponent(numberingCheckBox))
                .addContainerGap(36, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void dirButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirButtonActionPerformed
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        fileChooser.setDialogTitle(NbBundle.getMessage(ExportVisualPanel1.class,
                "LBL_ExportSongDialogTitle"));
        int resultOption = fileChooser.showDialog(SwingUtilities.getWindowAncestor(this),
                NbBundle.getMessage(ExportVisualPanel1.class, "LBL_PerformExport"));
        if (resultOption == JFileChooser.APPROVE_OPTION) {
            result.exportDir = fileChooser.getSelectedFile();
            dirTextField.setText(result.exportDir.getPath());
        }
    }//GEN-LAST:event_dirButtonActionPerformed

    private void preferredOnlyCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_preferredOnlyCheckBoxActionPerformed
        exportListModel.resultChanged(null);
    }//GEN-LAST:event_preferredOnlyCheckBoxActionPerformed

    private void numberingCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_numberingCheckBoxActionPerformed
        exportListModel.resultChanged(null);       
    }//GEN-LAST:event_numberingCheckBoxActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JComboBox conversionCombo;
    private javax.swing.JButton dirButton;
    private javax.swing.JTextField dirTextField;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JCheckBox numberingCheckBox;
    private javax.swing.JCheckBox preferredOnlyCheckBox;
    private javax.swing.JList resList;
    private javax.swing.JComboBox type2ExportCombo;
    // End of variables declaration//GEN-END:variables
}
